package com.hqyj.utils;

import com.hqyj.mapper.UserMapper;
import com.hqyj.pojo.User;
import com.hqyj.pojo.UserVO;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

/**
 * Created with IntelliJ IDEA.
 * User: zjz
 * Date: 2022/08/26 15:52
 * Description:
 * Version: V1.0
 */
public class MyShiroRealm extends AuthorizingRealm {

    @Autowired
    private UserMapper userMapper;


    /**
     * 已认证过用户的权限信息，获取授权信息，由开发者提供shiro框架，
     * @param principalCollection
     * @return
     */
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //获取当前已经认证过，但是待授权的账号
        String uAccount = (String) principalCollection.getPrimaryPrincipal();

        //根据用户账号查询权限
        UserVO userVO = userMapper.selectUserVOByAccount(uAccount);


        //根据获取的用户，遍历权限，将权限信息添加到roles集合中
        Set<String> roles = new HashSet<>();
        if (userVO.getUserPower().getPower() != null){
            roles.add(userVO.getUserPower().getPower());
        }

        //查询用户的权限授权信息
        Set<String> perm = new HashSet<>();
        //创建授权信息对象
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //设置角色信息
        info.setRoles(roles);
        info.setStringPermissions(perm);
        return info;
    }

    /**
     * 获取认证信息
     * 由开发者来编写，实现从数据库中查询待认证的用户的用户信息。以提供給shiro框架进行密码匹配工作
     * @param
     * @return
     * @throws AuthenticationException
     */
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //从token对象获取待登录的用户 的 用户名
        String uAccount = (String)token.getPrincipal();
        //从数据库中查询该username的用户信息
        User user = userMapper.selectOneByAccount(uAccount);

        //判断该用户是否存在
        if (user == null){
            throw new UnknownAccountException(uAccount + "不存在");
        }

        //用shiro的session来保存用户信息
        Session session = SecurityUtils.getSubject().getSession();

        //在shiro的session中共享数据，将该user保存到session中
        if (user.getRId() == 1) {
            //是管理员才保存
            session.setAttribute("user", user);
        }
        //创建一个SimpleAuthenticationInfo对象
        /* 使用4参数构造方法构造SimpleAuthenticationInfo对象
            SimpleAuthenticationInfo(Object principal,
             Object hashedCredentials,
             ByteSource credentialsSalt,
             String realmName)
         其中第二个参数：Object hashedCredentials 为散列过的用户密码
         其中第三个参数：ByteSource credentialsSalt 即为对用户密码散列时用到的salt，
         这里作为盐的字符串采用用户的账号名，与加密时使用的salt要一致才能认证成功
        */
        ByteSource salt = ByteSource.Util.bytes(user.getUAccount());

        //注意，数据库中的user的密码必须是要经过md5加密，不然还是会抛出异常！！！！！
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user.getUAccount(),user.getUPassword(),salt,getName());


        return authenticationInfo;
    }
}
